From 6a8362111e9279d92d0bd78834e4ad62f26ed119 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 11 Apr 2012 17:55:54 +0100 Subject: [PATCH] window: Add initial support for client-side decorations under Wayland This change comprises four main parts: * the creation of the widgets that form the decorations, * implementation of get_preferred_height/width, and the for_width/for_height variants, * taking the decorations into account when allocating, * and drawing the decorations themselves. Kristian did the bulk of the original work on this but any bugs are almost certainly mine through the many refactorings and rebasings. --- gtk/gtkwindow.c | 621 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 594 insertions(+), 27 deletions(-) diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index c0dc07e970..98ef7e55bd 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -49,6 +49,9 @@ #include "gtkintl.h" #include "gtkstylecontextprivate.h" #include "gtktypebuiltins.h" +#include "gtkbox.h" +#include "gtkbutton.h" +#include "gtkheaderbar.h" #include "a11y/gtkwindowaccessible.h" #include "deprecated/gtkstyle.h" @@ -57,6 +60,10 @@ #include "x11/gdkx.h" #endif +#ifdef GDK_WINDOWING_WAYLAND +#include "wayland/gdkwayland.h" +#endif + /** * SECTION:gtkwindow * @title: GtkWindow @@ -134,6 +141,12 @@ struct _GtkWindowPrivate guint auto_mnemonics_timeout_id; + GtkWidget *title_box; + GtkWidget *title_icon; + GtkWidget *title_min_button; + GtkWidget *title_max_button; + GtkWidget *title_close_button; + /* The following flags are initially TRUE (before a window is mapped). * They cause us to compute a configure request that involves * default-only parameters. Once mapped, we set them to FALSE. @@ -183,6 +196,7 @@ struct _GtkWindowPrivate * grip-visible" notification */ guint gravity : 5; /* GdkGravity */ + guint client_decorated : 1; /* Decorations drawn client-side */ }; @@ -348,6 +362,10 @@ static void gtk_window_style_updated (GtkWidget *widget); static gboolean gtk_window_state_event (GtkWidget *widget, GdkEventWindowState *event); static void gtk_window_check_resize (GtkContainer *container); +static void gtk_window_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); static gint gtk_window_focus (GtkWidget *widget, GtkDirectionType direction); static void gtk_window_move_focus (GtkWidget *widget, @@ -429,6 +447,23 @@ static void gtk_window_on_theme_variant_changed (GtkSettings *settings, #endif static void gtk_window_set_theme_variant (GtkWindow *window); + +static void gtk_window_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_window_get_preferred_width_for_height (GtkWidget *widget, + gint height, + gint *minimum_size, + gint *natural_size); + +static void gtk_window_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size); +static void gtk_window_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum_size, + gint *natural_size); + static GSList *toplevel_list = NULL; static guint window_signals[LAST_SIGNAL] = { 0 }; static GList *default_icon_list = NULL; @@ -589,8 +624,13 @@ gtk_window_class_init (GtkWindowClass *klass) widget_class->direction_changed = gtk_window_direction_changed; widget_class->state_changed = gtk_window_state_changed; widget_class->style_updated = gtk_window_style_updated; + widget_class->get_preferred_width = gtk_window_get_preferred_width; + widget_class->get_preferred_width_for_height = gtk_window_get_preferred_width_for_height; + widget_class->get_preferred_height = gtk_window_get_preferred_height; + widget_class->get_preferred_height_for_width = gtk_window_get_preferred_height_for_width; container_class->check_resize = gtk_window_check_resize; + container_class->forall = gtk_window_forall; klass->set_focus = gtk_window_real_set_focus; @@ -1115,6 +1155,49 @@ gtk_window_class_init (GtkWindowClass *klass) gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_WINDOW_ACCESSIBLE); } +static void +gtk_window_title_min_clicked (GtkWidget *widget, gpointer data) +{ + GtkWindow *window = (GtkWindow *)data; + + gtk_window_iconify (window); +} + +static void +gtk_window_title_max_clicked (GtkWidget *widget, gpointer data) +{ + GtkWindow *window = (GtkWindow *)data; + GdkWindowState state = gdk_window_get_state (gtk_widget_get_window (widget)); + + if (state & GDK_WINDOW_STATE_MAXIMIZED) + gtk_window_unmaximize (window); + else + gtk_window_maximize (window); +} + +static gboolean +send_delete_event (gpointer data) +{ + GtkWidget *window = GTK_WIDGET (data); + GdkEvent *event; + + event = gdk_event_new (GDK_DELETE); + + event->any.window = g_object_ref (gtk_widget_get_window (window)); + event->any.send_event = TRUE; + + gtk_main_do_event (event); + gdk_event_free (event); + + return G_SOURCE_REMOVE; +} + +static void +gtk_window_title_close_clicked (GtkWidget *button, gpointer data) +{ + gdk_threads_add_idle (send_delete_event, data); +} + static void gtk_window_init (GtkWindow *window) { @@ -1634,10 +1717,10 @@ gtk_window_set_title (GtkWindow *window, priv->title = new_title; if (gtk_widget_get_realized (widget)) - { - gdk_window_set_title (gtk_widget_get_window (widget), - priv->title); - } + gdk_window_set_title (gtk_widget_get_window (widget), priv->title); + + if (priv->title_box != NULL) + gtk_header_bar_set_title (GTK_HEADER_BAR (priv->title_box), priv->title); g_object_notify (G_OBJECT (window), "title"); } @@ -3322,7 +3405,7 @@ gtk_window_set_decorated (GtkWindow *window, gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); if (gdk_window) { - if (priv->decorated) + if (priv->decorated && !priv->client_decorated) gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL); else @@ -4755,6 +4838,68 @@ gtk_window_finalize (GObject *object) G_OBJECT_CLASS (gtk_window_parent_class)->finalize (object); } +static void +create_decoration (GtkWidget *widget) +{ + GtkWindow *window = GTK_WINDOW (widget); + GtkWindowPrivate *priv = window->priv; + GtkStyleContext *context; + const char *title = "GtkWindow"; + + /* Clien decorations already created */ + if (priv->client_decorated) + return; + + if (priv->type == GTK_WINDOW_POPUP) + return; + +#ifdef GDK_WINDOWING_WAYLAND + if (!GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (widget))) + return; +#else + return; +#endif + + if (!priv->decorated) + return; + + priv->client_decorated = TRUE; + + priv->title_box = gtk_header_bar_new (); + g_object_set (priv->title_box, + "spacing", 0, + "hpadding", 0, + "vpadding", 0, + NULL); + context = gtk_widget_get_style_context (priv->title_box); + gtk_style_context_add_class (context, "titlebar"); + gtk_widget_set_parent (priv->title_box, GTK_WIDGET (window)); + + if (priv->title) + title = priv->title; + gtk_header_bar_set_title (GTK_HEADER_BAR (priv->title_box), title); + + priv->title_min_button = gtk_button_new_with_label ("_"); + gtk_widget_set_can_focus (priv->title_min_button, FALSE); + gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->title_box), priv->title_min_button); + g_signal_connect (priv->title_min_button, "clicked", + G_CALLBACK (gtk_window_title_min_clicked), window); + + priv->title_max_button = gtk_button_new_with_label ("\342\226\253"); + gtk_widget_set_can_focus (priv->title_max_button, FALSE); + gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->title_box), priv->title_max_button); + g_signal_connect (priv->title_max_button, "clicked", + G_CALLBACK (gtk_window_title_max_clicked), window); + + priv->title_close_button = gtk_button_new_with_label ("×"); + gtk_widget_set_can_focus (priv->title_close_button, FALSE); + gtk_header_bar_pack_end (GTK_HEADER_BAR (priv->title_box), priv->title_close_button); + g_signal_connect (priv->title_close_button, "clicked", + G_CALLBACK (gtk_window_title_close_clicked), window); + + gtk_widget_show_all (priv->title_box); +} + static void gtk_window_show (GtkWidget *widget) { @@ -4892,11 +5037,12 @@ gtk_window_map (GtkWidget *widget) gtk_widget_set_mapped (widget, TRUE); child = gtk_bin_get_child (&(window->bin)); - if (child && - gtk_widget_get_visible (child) && - !gtk_widget_get_mapped (child)) + if (child != NULL && gtk_widget_get_visible (child)) gtk_widget_map (child); + if (priv->title_box != NULL) + gtk_widget_map (priv->title_box); + gdk_window = gtk_widget_get_window (widget); if (priv->maximize_initially) @@ -5051,8 +5197,11 @@ gtk_window_unmap (GtkWidget *widget) priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0; priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0; + if (priv->title_box != NULL) + gtk_widget_unmap (priv->title_box); + child = gtk_bin_get_child (&(window->bin)); - if (child) + if (child != NULL) gtk_widget_unmap (child); } @@ -5138,6 +5287,8 @@ gtk_window_realize (GtkWidget *widget) window = GTK_WINDOW (widget); priv = window->priv; + create_decoration (widget); + gtk_widget_get_allocation (widget, &allocation); if (gtk_widget_get_parent_window (widget)) @@ -5224,6 +5375,7 @@ gtk_window_realize (GtkWidget *widget) attributes.height = allocation.height; attributes.event_mask = gtk_widget_get_events (widget); attributes.event_mask |= (GDK_EXPOSURE_MASK | + GDK_BUTTON_PRESS_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | @@ -5253,7 +5405,7 @@ gtk_window_realize (GtkWidget *widget) if (priv->wm_role) gdk_window_set_role (gdk_window, priv->wm_role); - if (!priv->decorated) + if (!priv->decorated || priv->client_decorated) gdk_window_set_decorations (gdk_window, 0); if (!priv->deletable) @@ -5502,6 +5654,34 @@ set_grip_position (GtkWindow *window) rect.width, rect.height); } +static void +get_decoration_borders (GtkWidget *widget, + GtkBorder *title_border, + GtkBorder *window_border) +{ + GtkStyleContext *context; + GtkStateFlags state; + + context = gtk_widget_get_style_context (widget); + state = gtk_style_context_get_state (context); + + if (title_border != NULL) + { + gtk_style_context_save (context); + gtk_style_context_add_class (context, "titlebar"); + gtk_style_context_get_border (context, state, title_border); + gtk_style_context_restore (context); + } + + if (window_border != NULL) + { + gtk_style_context_save (context); + gtk_style_context_add_class (context, "window-border"); + gtk_style_context_get_border (context, state, window_border); + gtk_style_context_restore (context); + } +} + /* _gtk_window_set_allocation: * @window: a #GtkWindow * @allocation: the original allocation for the window @@ -5527,12 +5707,68 @@ _gtk_window_set_allocation (GtkWindow *window, GtkAllocation *allocation_out) { GtkWidget *widget = (GtkWidget *)window; + GtkWindowPrivate *priv = window->priv; + GtkAllocation child_allocation; + guint border_width; + GtkBorder title_border = { 0 }; + GtkBorder window_border = { 0 }; + gint title_height = 0; g_assert (allocation != NULL); g_assert (allocation_out != NULL); gtk_widget_set_allocation (widget, allocation); + if (priv->title_box != NULL) + get_decoration_borders (widget, &title_border, &window_border); + else + get_decoration_borders (widget, NULL, &window_border); + + border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); + + /* Apply border width */ + child_allocation = *allocation; + child_allocation.x += border_width; + child_allocation.y += border_width; + child_allocation.width = MAX (1, child_allocation.width - border_width * 2); + child_allocation.height = MAX (1, child_allocation.height - border_width * 2); + + if (priv->title_box != NULL && + priv->client_decorated && + priv->decorated) + { + GtkAllocation title_allocation; + + gtk_widget_get_preferred_height (priv->title_box, + NULL, + &title_height); + + title_allocation.x = title_border.left + + window_border.left; + title_allocation.y = title_border.top + + window_border.top; + title_allocation.width = + MAX (1, (gint) allocation->width - + title_border.left - title_border.right - + window_border.left - window_border.right); + title_allocation.height = title_height; + + gtk_widget_size_allocate (priv->title_box, &title_allocation); + } + + if (priv->client_decorated && priv->decorated) + { + child_allocation.x += window_border.left; + child_allocation.y += window_border.top + + title_height + + title_border.top + + title_border.bottom; + child_allocation.width -= (window_border.left + + window_border.right); + child_allocation.height -= (child_allocation.y + + window_border.bottom); + } + if (gtk_widget_get_realized (widget)) { /* If it's not a toplevel we're embedded, we need to resize @@ -5551,7 +5787,7 @@ _gtk_window_set_allocation (GtkWindow *window, } } - *allocation_out = *allocation; + *allocation_out = child_allocation; } static void @@ -5559,23 +5795,14 @@ gtk_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkWindow *window = GTK_WINDOW (widget); - GtkAllocation child_allocation; GtkWidget *child; - guint border_width; + GtkAllocation child_allocation; _gtk_window_set_allocation (window, allocation, &child_allocation); child = gtk_bin_get_child (&(window->bin)); if (child && gtk_widget_get_visible (child)) - { - border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); - child_allocation.x += border_width; - child_allocation.y += border_width; - child_allocation.width = MAX (1, child_allocation.width - border_width * 2); - child_allocation.height = MAX (1, child_allocation.height - border_width * 2); - - gtk_widget_size_allocate (child, &child_allocation); - } + gtk_widget_size_allocate (child, &child_allocation); } static gint @@ -5904,15 +6131,20 @@ gtk_window_get_resize_grip_area (GtkWindow *window, GdkRectangle *rect) { GtkWidget *widget = GTK_WIDGET (window); + GtkWindowPrivate *priv = window->priv; GtkAllocation allocation; gint grip_width; gint grip_height; + GtkBorder window_border = { 0 }; g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); if (!window->priv->has_resize_grip) return FALSE; + if (priv->client_decorated) + get_decoration_borders (widget, NULL, &window_border); + gtk_widget_get_allocation (widget, &allocation); gtk_widget_style_get (widget, @@ -5928,10 +6160,12 @@ gtk_window_get_resize_grip_area (GtkWindow *window, rect->width = grip_width; rect->height = grip_height; - rect->y = allocation.y + allocation.height - grip_height; + rect->y = allocation.y + allocation.height - + grip_height - window_border.bottom; if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) - rect->x = allocation.x + allocation.width - grip_width; + rect->x = allocation.x + allocation.width - + grip_width - window_border.right; else rect->x = allocation.x; @@ -6096,6 +6330,32 @@ gtk_window_button_press_event (GtkWidget *widget, return TRUE; } + else if (priv->client_decorated && + priv->decorated && + priv->title_box != NULL) + { + GtkAllocation allocation; + int border_width; + + gtk_widget_get_allocation (priv->title_box, &allocation); + border_width = + gtk_container_get_border_width (GTK_CONTAINER (priv->title_box)); + + if (allocation.x - border_width <= event->x && + event->x < allocation.x + border_width + allocation.width && + allocation.y - border_width <= event->y && + event->y < allocation.y + border_width + allocation.height) + { + gdk_window_begin_move_drag_for_device (gtk_widget_get_window(widget), + gdk_event_get_device((GdkEvent *) event), + event->button, + event->x_root, + event->y_root, + event->time); + + return TRUE; + } + } return FALSE; } @@ -6261,6 +6521,25 @@ gtk_window_check_resize (GtkContainer *container) gtk_window_move_resize (GTK_WINDOW (container)); } +static void +gtk_window_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + GtkWindow *window = GTK_WINDOW (container); + GtkWindowPrivate *priv = window->priv; + GtkWidget *child; + + child = gtk_bin_get_child (GTK_BIN (container)); + if (child != NULL) + (* callback) (child, callback_data); + + if (include_internals && + priv->title_box != NULL) + (* callback) (priv->title_box, callback_data); +} + static gboolean gtk_window_focus (GtkWidget *widget, GtkDirectionType direction) @@ -6438,6 +6717,239 @@ gtk_window_real_set_focus (GtkWindow *window, } } +static void +gtk_window_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + GtkWindow *window; + GtkWidget *child; + GtkWindowPrivate *priv; + guint border_width; + gint title_min = 0, title_nat = 0; + gint child_min = 0, child_nat = 0; + GtkBorder title_border = { 0, }; + GtkBorder window_border = { 0 }; + + window = GTK_WINDOW (widget); + priv = window->priv; + child = gtk_bin_get_child (GTK_BIN (window)); + + border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); + + if (priv->client_decorated && + priv->decorated) + { + if (priv->title_box != NULL) + { + gtk_widget_get_preferred_width (priv->title_box, + &title_min, &title_nat); + get_decoration_borders (widget, &title_border, &window_border); + } + else + { + get_decoration_borders (widget, NULL, &window_border); + } + + title_min += border_width * 2 + + title_border.left + title_border.right + + window_border.left + window_border.right; + title_nat += border_width * 2 + + title_border.left + title_border.right + + window_border.left + window_border.right; + } + + if (child && gtk_widget_get_visible (child)) + { + gtk_widget_get_preferred_width (child, &child_min, &child_nat); + child_min += border_width * 2 + + window_border.left + window_border.right; + child_nat += border_width * 2 + + window_border.left + window_border.right; + } + + *minimum_size = MAX (title_min, child_min); + *natural_size = MAX (title_nat, child_nat); +} + + +static void +gtk_window_get_preferred_width_for_height (GtkWidget *widget, + gint height, + gint *minimum_size, + gint *natural_size) +{ + GtkWindow *window; + GtkWidget *child; + GtkWindowPrivate *priv; + guint border_width; + gint title_min = 0, title_nat = 0; + gint child_min = 0, child_nat = 0; + GtkBorder title_border = { 0, }; + GtkBorder window_border = { 0 }; + + window = GTK_WINDOW (widget); + priv = window->priv; + child = gtk_bin_get_child (GTK_BIN (window)); + + border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); + + if (priv->client_decorated && + priv->decorated) + { + if (priv->title_box != NULL) + { + gtk_widget_get_preferred_width_for_height (priv->title_box, + height, + &title_min, &title_nat); + get_decoration_borders (widget, &title_border, &window_border); + } + else + { + get_decoration_borders (widget, NULL, &window_border); + } + + title_min += border_width * 2 + + title_border.left + title_border.right + + window_border.left + window_border.right; + title_nat += border_width * 2 + + title_border.left + title_border.right + + window_border.left + window_border.right; + } + + if (child && gtk_widget_get_visible (child)) + { + gtk_widget_get_preferred_width_for_height (child, + height, + &child_min, &child_nat); + child_min += border_width * 2 + + window_border.left + window_border.right; + child_nat += border_width * 2 + + window_border.left + window_border.right; + } + + *minimum_size = MAX (title_min, child_min); + *natural_size = MAX (title_nat, child_nat); +} + +static void +gtk_window_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) +{ + GtkWindow *window; + GtkWindowPrivate *priv; + GtkWidget *child; + guint border_width; + int title_min = 0; + int title_height = 0; + GtkBorder title_border = { 0, }; + GtkBorder window_border = { 0 }; + + window = GTK_WINDOW (widget); + priv = window->priv; + child = gtk_bin_get_child (GTK_BIN (window)); + + *minimum_size = 0; + *natural_size = 0; + + border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); + + if (priv->client_decorated && + priv->decorated) + { + if (priv->title_box != NULL) + { + gtk_widget_get_preferred_height (priv->title_box, + &title_min, + &title_height); + get_decoration_borders (widget, &title_border, &window_border); + } + else + { + get_decoration_borders (widget, NULL, &window_border); + } + + *minimum_size = title_min + + title_border.top + title_border.bottom + + window_border.top + window_border.bottom; + + *natural_size = title_height + + title_border.top + title_border.bottom + + window_border.top + window_border.bottom; + } + + if (child && gtk_widget_get_visible (child)) + { + gint child_min, child_nat; + gtk_widget_get_preferred_height (child, &child_min, &child_nat); + + *minimum_size += child_min + 2 * border_width; + *natural_size += child_nat + 2 * border_width; + } +} + + +static void +gtk_window_get_preferred_height_for_width (GtkWidget *widget, + gint width, + gint *minimum_size, + gint *natural_size) +{ + GtkWindow *window; + GtkWindowPrivate *priv; + GtkWidget *child; + guint border_width; + int title_min = 0; + int title_height = 0; + GtkBorder title_border = { 0, }; + GtkBorder window_border = { 0 }; + + window = GTK_WINDOW (widget); + priv = window->priv; + child = gtk_bin_get_child (GTK_BIN (window)); + + *minimum_size = 0; + *natural_size = 0; + + border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); + + if (priv->client_decorated && + priv->decorated) + { + if (priv->title_box != NULL) + { + gtk_widget_get_preferred_height_for_width (priv->title_box, + width, + &title_min, + &title_height); + get_decoration_borders (widget, &title_border, &window_border); + } + else + { + get_decoration_borders (widget, NULL, &window_border); + } + + *minimum_size = title_min + + title_border.top + title_border.bottom + + window_border.top + window_border.bottom; + + *natural_size = title_height + + title_border.top + title_border.bottom + + window_border.top + window_border.bottom; + } + + if (child && gtk_widget_get_visible (child)) + { + gint child_min, child_nat; + gtk_widget_get_preferred_height_for_width (child, width, + &child_min, &child_nat); + + *minimum_size += child_min + 2 * border_width; + *natural_size += child_nat + 2 * border_width; + } +} + /** * _gtk_window_unset_focus_and_default: * @window: a #GtkWindow @@ -7566,15 +8078,70 @@ gtk_window_draw (GtkWidget *widget, GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv; GtkStyleContext *context; gboolean ret = FALSE; + GtkAllocation allocation; + GtkBorder title_border = { 0 }; + GtkBorder window_border = {}; context = gtk_widget_get_style_context (widget); + if (priv->title_box != NULL) + get_decoration_borders (widget, &title_border, &window_border); + else + get_decoration_borders (widget, NULL, &window_border); + if (!gtk_widget_get_app_paintable (widget) && gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget))) { - gtk_render_background (context, cr, 0, 0, - gtk_widget_get_allocated_width (widget), - gtk_widget_get_allocated_height (widget)); + gtk_style_context_save (context); + + gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND); + + if (priv->client_decorated && + priv->decorated) + { + gtk_style_context_add_class (context, "window-border"); + gtk_widget_get_allocation (widget, &allocation); + gtk_render_background (context, cr, + window_border.left, + window_border.top, + allocation.width - + (window_border.left + + window_border.right), + allocation.height - + (window_border.top + + window_border.bottom)); + gtk_render_frame (context, cr, + 0, 0, allocation.width, allocation.height); + } + else + { + gtk_widget_get_allocation (widget, &allocation); + gtk_render_background (context, cr, + 0, 0, allocation.width, allocation.height); + } + + gtk_style_context_restore (context); + } + + if (priv->title_box != NULL) + { + gtk_style_context_save (context); + gtk_style_context_add_class (context, "titlebar"); + gtk_widget_get_allocation (priv->title_box, &allocation); + + /* Why do these subtract ? */ + gtk_render_background (context, cr, + allocation.x - title_border.left, + allocation.y - title_border.top, + allocation.width + title_border.left + title_border.right, + allocation.height + title_border.top + title_border.left); + gtk_render_frame (context, cr, + allocation.x - title_border.left, + allocation.y - title_border.top, + allocation.width + title_border.left + title_border.right, + allocation.height + title_border.top + title_border.left); + + gtk_style_context_restore (context); } if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw) -- 2.30.2